// rgb565转灰度图像，并填充到rgb565原通道，以原时序输出，但延迟了6个时钟周期
module rbg565_gray (
    input             cam_pclk  ,
    input             rst_n     ,
    input             cam_vsync ,
    input             cam_href  ,
    input      [15:0] cam_data  ,
    output            gray_vsync, 
    output            gray_href ,
    output     [15:0] gray_data ,
    output reg        gray_data_valid
);
// reg define
reg [15:0] r1, g1, b1, r2, g2, b2, r3, g3, b3;
reg [15:0] y1, cb1, cr1;
reg [ 7:0] y2, cb2, cr2;
reg [ 5:0] href_d3, vsync_d3;       // 中间处理花3拍

// wire define
wire [7:0] r0, g0, b0;
//              main code
// rgb565转rgb888
assign r0 = {cam_data[15:11], cam_data[13:11]};
assign g0 = {cam_data[10: 5], cam_data[ 6: 5]};
assign b0 = {cam_data[ 4: 0], cam_data[ 2: 0]};

// 灰度图像输出给到rgb565的通道
assign gray_data = {y2[7:3], y2[7:2], y2[7:3]};

// 乘法部分赋值 
always @(posedge cam_pclk or negedge rst_n) begin
    if(~rst_n)begin
        {r1, g1, b1} <= {3{16'd0}};
        // {r2, g2, b2} <= {3{16'd0}};
        // {r3, g3, b3} <= {3{16'd0}};
    end
    else begin
        {r1, g1, b1} <= {r0 *  77, g0 * 150, b0 *  29};
        // {r2, g2, b2} <= {r0 *  43, g0 *  85, b0 * 128};
        // {r3, g3, b3} <= {r0 * 128, g0 * 107, b0 *  21};
    end
end

// 加法部分赋值（加减法个数不超过3个）
always @(posedge cam_pclk or negedge rst_n) begin
    if(~rst_n)begin
         y1 <= 16'd0;
        // cb1 <= 16'd0;
        // cr1 <= 16'd0;
    end
    else begin
         y1 <= r1 + g1 + b1;
        // cb1 <= b2 - g2 - r2 + 16'd32768;
        // cr1 <= r3 - g3 - b3 + 16'd32768;
    end
end

// YCbCr格式输出
always @(posedge cam_pclk or negedge rst_n) begin
    if(~rst_n)begin
         y2 <= 8'd0;
        // cb2 <= 8'd0;
        // cr2 <= 8'd0;
    end
    else begin
         y2 <= y1 [15:8];
        // cb2 <= cb1[15:8];
        // cr2 <= cr1[15:8];
    end
end

// 延迟
always @(posedge cam_pclk or negedge rst_n) begin
    if(~rst_n)begin
        vsync_d3 <= 5'd0;
        href_d3 <= 5'd0;
    end
    else begin
        vsync_d3 <= {vsync_d3[1:0], cam_vsync};
        href_d3 <= {href_d3[1:0], cam_href};
    end
end 
assign gray_vsync = vsync_d3[2]; // 延迟3拍
assign gray_href = href_d3[2];

// gray_data_valid
always @(posedge cam_pclk or negedge rst_n) begin
    if(~rst_n)
        gray_data_valid <= 1'd0;
    else if(gray_href)
        gray_data_valid <= ~gray_data_valid;
    else 
        gray_data_valid <= 1'd0;
end
endmodule